home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / dev / c / agl103p.lha / src / agl / matrix.c < prev    next >
C/C++ Source or Header  |  1994-12-08  |  24KB  |  1,099 lines

  1. /******************************************************************************
  2.  
  3. Copyright © 1994 Jason Weber
  4. All Rights Reserved
  5.  
  6. $Id: matrix.c,v 1.2.1.6 1994/12/09 05:29:56 jason Exp $
  7.  
  8. $Log: matrix.c,v $
  9.  * Revision 1.2.1.6  1994/12/09  05:29:56  jason
  10.  * added copyright
  11.  *
  12.  * Revision 1.2.1.5  1994/11/18  07:49:22  jason
  13.  * added matrix load and get
  14.  *
  15.  * Revision 1.2.1.4  1994/09/13  03:48:33  jason
  16.  * added fixed-point test
  17.  *
  18.  * Revision 1.2.1.3  1994/04/06  02:39:10  jason
  19.  * Separate rotation for X, Y, and Z axes
  20.  *
  21.  * Revision 1.2.1.2  1994/04/02  03:33:11  jason
  22.  * acceleration matrix operations: no more 4D arrays
  23.  * needs cleaning and further optimizations
  24.  *
  25.  * Revision 1.2.1.1  1994/03/29  05:41:32  jason
  26.  * Added RCS Header
  27.  
  28. ******************************************************************************/
  29.  
  30.  
  31. #ifndef NOT_EXTERN
  32. #include"agl.h"
  33. #endif
  34.  
  35. /*
  36.  *  near and far cutting planes are included, but have no effect
  37.  */
  38.  
  39. #define    MATRIX_DEBUG        FALSE
  40. #define    VERTEX_DEBUG        FALSE
  41.  
  42. #define    CLEAR_PROJECTION    TRUE
  43. #define    FAST_PUSH            TRUE
  44. #define    FAST_ROT            TRUE
  45. #define SINE_TABLE            TRUE
  46. #define FIXED_POINT            FALSE
  47.  
  48.  
  49. /* ProjectionType enumeration */
  50. #define PROJ_ORTHO            0
  51. #define PROJ_PERSPECTIVE    1
  52. #define PROJ_CUSTOM            2
  53.  
  54.  
  55. /* MACRO'S */
  56. #define PROJECTION(Y,X)    ProjectionPointer[(Y<<2)+X]
  57. #define TRANSLATION(X)    TranslatePointer[X]
  58. #define ROTATION(Y,X)    RotatePointer[(Y<<2)+X]
  59.  
  60. #if FIXED_POINT
  61.  
  62.     #define FIXING_POINT    10000
  63.  
  64.     #define FIXVALUE(x)        (x*FIXING_POINT)
  65.     #define FIXBACK(x)        (x/(float)FIXING_POINT)
  66.     #define FIXMULT(x,y)    (x*y/FIXING_POINT)
  67.     #define FIXDIVIDE(x,y)    (FIXING_POINT*x/y)
  68.  
  69.     #define FIXTYPE            long long
  70.  
  71. #else
  72.  
  73.     #define FIXVALUE(x)        x
  74.     #define FIXBACK(x)        x
  75.     #define FIXMULT(x,y)    (x*y)
  76.     #define FIXDIVIDE(x,y)    (x/y)
  77.  
  78.     #define FIXTYPE            float
  79.  
  80. #endif
  81.  
  82.  
  83. /* isolated prototypes */
  84. void rotate_translate_position(FIXTYPE vert[3],FIXTYPE rvert[3]);
  85. void rotate_position(FIXTYPE vert[3],FIXTYPE rvert[3]);
  86. void project_vertex(FIXTYPE in[3],FIXTYPE out[3]);
  87.  
  88.  
  89. static Matrix IdentityMatrix=
  90.     {
  91.     1.0, 0.0, 0.0, 0.0,
  92.     0.0, 1.0, 0.0, 0.0,
  93.     0.0, 0.0, 1.0, 0.0,
  94.     0.0, 0.0, 0.0, 1.0,
  95.     };
  96.  
  97. short MatrixLevel[MAX_WINDOWS];
  98. short ProjectionType[MAX_WINDOWS];
  99. short OrthoAligned[MAX_WINDOWS];
  100. short MatrixMode=MSINGLE;
  101.  
  102. FIXTYPE Projection[MAX_WINDOWS][4][4];
  103. FIXTYPE Transformation[MAX_WINDOWS][MATRIXSTACKDEPTH][4][4];
  104.  
  105. FIXTYPE Sine[3600];
  106.  
  107. FIXTYPE *RotatePointer,*TranslatePointer,*ProjectionPointer;
  108.  
  109.  
  110. /******************************************************************************
  111. void    init_matrices(void)
  112.  
  113. ******************************************************************************/
  114. /*PROTOTYPE*/
  115. void init_matrices(void)
  116.     {
  117.     long wid;
  118.     short x,y;
  119.  
  120. #if MATRIX_DEBUG
  121.     printf("init_matrices()\n");
  122. #endif
  123.  
  124.     /* create sin table */
  125.     for(x=0;x<3600;x++)
  126.         Sine[x]=FIXVALUE(sin(x/10.0*DEG));
  127.  
  128.     for(wid=0;wid<MAX_WINDOWS;wid++)
  129.         {
  130.         MatrixLevel[wid]=0;
  131.  
  132.         for(x=0;x<4;x++)
  133.             for(y=0;y<4;y++)
  134.                 if(x==y)
  135.                     Transformation[wid][0][y][x]=FIXVALUE(1.0);
  136.                 else
  137.                     Transformation[wid][0][y][x]=FIXVALUE(0.0);
  138.         }
  139.     }
  140.  
  141.  
  142. /******************************************************************************
  143. void    reset_matrix_pointers(void)
  144.  
  145.     call from winset() to reset pointers to transform structures
  146.  
  147. ******************************************************************************/
  148. /*PROTOTYPE*/
  149. void reset_matrix_pointers(void)
  150.     {
  151.     short m;
  152.  
  153.     m=MatrixLevel[CurrentWid];
  154.  
  155.     RotatePointer= &(Transformation[CurrentWid][m][0][0]);
  156.     TranslatePointer= &(Transformation[CurrentWid][m][3][0]);
  157.     ProjectionPointer= &(Projection[CurrentWid][0][0]);
  158.     }
  159.  
  160.  
  161. /******************************************************************************
  162. void pushmatrix(void)
  163.  
  164. ******************************************************************************/
  165. /*PROTOTYPE*/
  166. void pushmatrix(void)
  167.     {
  168. /*     short x,y; */
  169.     short m;
  170.  
  171. #if MATRIX_DEBUG
  172.     printf("pushmatrix() -> %d\n",MatrixLevel[CurrentWid]+1);
  173. #endif
  174.  
  175.     if(MatrixLevel[CurrentWid]==MATRIXSTACKDEPTH-1)
  176.         GL_error("Too many matrices pushed");
  177.     else
  178.         {
  179.         m= ++MatrixLevel[CurrentWid];
  180.  
  181. #if FAST_PUSH
  182.  
  183.         memcpy(RotatePointer+16,RotatePointer,16*sizeof(FIXTYPE));
  184.  
  185. #else
  186.         for(y=0;y<3;y++)
  187.             {
  188.             Translation[CurrentWid][m][y]=Translation[CurrentWid][m-1][y];
  189.             for(x=0;x<3;x++)
  190.                 Rotate[CurrentWid][m][y][x]=Rotate[CurrentWid][m-1][y][x];
  191.             }
  192. #endif
  193.  
  194.         /* move up pointers */
  195.         RotatePointer+=16;
  196.         TranslatePointer+=16;
  197.         }
  198.     }
  199.  
  200.  
  201. /******************************************************************************
  202. void    popmatrix(void)
  203.  
  204. ******************************************************************************/
  205. /*PROTOTYPE*/
  206. void popmatrix(void)
  207.     {
  208. #if MATRIX_DEBUG
  209.     printf("popmatrix() -> %d\n",MatrixLevel[CurrentWid]-1);
  210. #endif
  211.  
  212.     if(MatrixLevel[CurrentWid]==0)
  213.         GL_error("Too many matrices popped");
  214.     else
  215.         {
  216.         MatrixLevel[CurrentWid]--;
  217.  
  218.         /* move up pointers */
  219.         RotatePointer-=16;
  220.         TranslatePointer-=16;
  221.         }
  222.  
  223.     if(MatrixLevel[CurrentWid]==0)    /* gotta have some way to go back */
  224.         Dimensions[CurrentWid]=2;
  225.     }
  226.  
  227.  
  228. /******************************************************************************
  229. void    mmode(short mode)
  230.  
  231.     set matrix mode:
  232.         MSINGLE
  233.         MVIEWING
  234.         MPROJECTION
  235.         MTEXTURE
  236.  
  237. ******************************************************************************/
  238. /*PROTOTYPE*/
  239. void mmode(short mode)
  240.     {
  241.     if(mode!=MSINGLE && mode!=MVIEWING && mode!=MPROJECTION && mode!=MTEXTURE )
  242.         {
  243.         GL_error("(INTERNAL) getmatrix: illegal MatrixMode");
  244.         }
  245.     else
  246.         {
  247.         MatrixMode=mode;
  248.  
  249.         if(mode==MSINGLE)
  250.             GL_error("MSINGLE obsolete: using MVIEWING");
  251.         
  252.         if(mode==MTEXTURE)
  253.             GL_error("MTEXTURE not supported");
  254.         }
  255.     }
  256.  
  257.  
  258. /******************************************************************************
  259. long    getmmode(void)
  260.  
  261. ******************************************************************************/
  262. /*PROTOTYPE*/
  263. long getmmode(void)
  264.     {
  265.     return MatrixMode;
  266.     }
  267.  
  268.  
  269. /******************************************************************************
  270. void    getmatrix(Matrix  m)
  271.  
  272.     give user the current transform
  273.  
  274. ******************************************************************************/
  275. /*PROTOTYPE*/
  276. void getmatrix(Matrix  m)
  277.     {
  278.     switch(MatrixMode)
  279.         {
  280.         case MSINGLE:
  281.         case MVIEWING:
  282.             memcpy(m,RotatePointer,sizeof(Matrix));
  283.             break;
  284.  
  285.         case MPROJECTION:
  286.             memcpy(m,ProjectionPointer,sizeof(Matrix));
  287.             break;
  288.  
  289.         case MTEXTURE:
  290.             memset(m,0,sizeof(Matrix));
  291.             break;
  292.  
  293.         default:
  294.             GL_error("(INTERNAL) getmatrix: illegal MatrixMode");
  295.             break;
  296.         }
  297.     }
  298.  
  299.  
  300. /******************************************************************************
  301. void    loadmatrix(Matrix  m)
  302.  
  303.     use the users custom matrix
  304.  
  305. ******************************************************************************/
  306. /*PROTOTYPE*/
  307. void loadmatrix(Matrix  m)
  308.     {
  309.     switch(MatrixMode)
  310.         {
  311.         case MSINGLE:
  312.         case MVIEWING:
  313.             memcpy(RotatePointer,m,sizeof(Matrix));
  314.             break;
  315.  
  316.         case MPROJECTION:
  317.             memcpy(ProjectionPointer,m,sizeof(Matrix));
  318.             ProjectionType[CurrentWid]=PROJ_CUSTOM;
  319.             break;
  320.  
  321.         case MTEXTURE:
  322.             GL_error("loadmatrix: MTEXTURE matrix mode not supported -> can't load matrix");
  323.             break;
  324.  
  325.         default:
  326.             GL_error("(INTERNAL) loadmatrix: illegal MatrixMode");
  327.             break;
  328.         }
  329.  
  330.     OneToOne[CurrentWid]=is_one_to_one(RotatePointer);
  331.     }
  332.  
  333.  
  334. /******************************************************************************
  335. void    multmatrix(Matrix  m)
  336.  
  337.     pre-multiply current matrix by user's custom transform
  338.  
  339. ******************************************************************************/
  340. /*PROTOTYPE*/
  341. void multmatrix(Matrix  m)
  342.     {
  343.     Matrix temp;
  344.  
  345.     short x,y;
  346.     short n;
  347.  
  348.     memcpy(temp,RotatePointer,sizeof(Matrix));
  349.  
  350.     for(y=0;y<4;y++)
  351.         for(x=0;x<4;x++)
  352.             {
  353.             ROTATION(y,x)=0;
  354.  
  355.             for(n=0;n<4;n++)
  356.                 ROTATION(y,x)+=m[y][n]*temp[n][x];
  357.             }
  358.  
  359.     OneToOne[CurrentWid]=is_one_to_one(RotatePointer);
  360.     }
  361.  
  362.  
  363. /******************************************************************************
  364. long    is_one_to_one(Matrix m)
  365.  
  366.     returns TRUE if given 4x4 matrix is an identity
  367.  
  368. ******************************************************************************/
  369. /*PROTOTYPE*/
  370. long is_one_to_one(Matrix m)
  371.     {
  372.     return OrthoAligned[CurrentWid] && viewport_aligned() &&
  373.                                                 memcmp(RotatePointer,IdentityMatrix,sizeof(Matrix))==0;
  374.     }
  375.  
  376.  
  377. /******************************************************************************
  378. void    project_vertex(FIXTYPE in[3],FIXTYPE out[3])
  379.  
  380.     applies perspective on transformed vertex
  381. ******************************************************************************/
  382. /*NO PROTOTYPE*/
  383. void project_vertex(FIXTYPE in[3],FIXTYPE out[3])
  384.     {
  385. #if !FAST_PROJECTION
  386.  
  387.     short x,m;
  388.     float sum,before[4],mid[4];
  389.  
  390.     switch(ProjectionType[CurrentWid])
  391.         {
  392.         case PROJ_ORTHO:
  393.             /* fast: compute only x and y for ortho projection */
  394.  
  395.             out[0]=FIXMULT(PROJECTION(0,0),in[0])+PROJECTION(3,0);
  396.             out[1]=FIXMULT(PROJECTION(1,1),in[1])+PROJECTION(3,1);
  397.             break;
  398.  
  399.         case PROJ_PERSPECTIVE:
  400.             /* fast: compute only x and y for perspective projection */
  401.  
  402.             /* mult and divide cancel fixed point effect */
  403.  
  404.             out[0]= -PROJECTION(0,0)*in[0]/in[2];
  405.             out[1]= -PROJECTION(1,1)*in[1]/in[2];
  406.             break;
  407.  
  408.         case PROJ_CUSTOM:
  409.             /* complete: general purpose, any transform matrix */
  410.  
  411.             for(x=0;x<3;x++)
  412.                 before[x]=in[x];
  413.             before[3]=1.0;
  414.  
  415.             for(x=0;x<4;x++)
  416.                 {
  417.                 sum=0.0;
  418.                 for(m=0;m<4;m++)
  419.                     sum+=PROJECTION(m,x)*before[m];
  420.  
  421.                 mid[x]=sum;
  422.                 }
  423.  
  424.             /* divide out range factor */
  425.             for(x=0;x<3;x++)
  426.                 out[x]= -mid[x]/mid[3];
  427.  
  428. /*                 out[y]=PROJECTION(3,2)*mid[y]/mid[3]; */
  429.  
  430. /*
  431.             for(m=0;m<4;m++)
  432.                 {
  433.                 for(x=0;x<4;x++)
  434.                     printf("%8.2f ",PROJECTION(m,x));
  435.  
  436.                 printf("\n");
  437.                 }
  438.  
  439.             printf("\nbefore\n");
  440.             for(x=0;x<4;x++)
  441.                 printf("%8.2f ",before[x]);
  442.  
  443.             printf("\nmid\n");
  444.             for(x=0;x<4;x++)
  445.                 printf("%8.2f ",mid[x]);
  446.  
  447.             printf("\nout\n");
  448.             for(x=0;x<4;x++)
  449.                 printf("%8.2f ",out[x]);
  450. */
  451.             break;
  452.         }
  453.     }
  454.  
  455.  
  456. /******************************************************************************
  457. void    perspective(long angle,float aspect,float near,float far)
  458.  
  459.     angle in integer number of tenths of degrees
  460.  
  461.     sets Projection[][]
  462. ******************************************************************************/
  463. /*PROTOTYPE*/
  464. void perspective(long angle,float aspect,float near,float far)
  465.     {
  466.     float fovy,cot;
  467.  
  468. #if MATRIX_DEBUG
  469.     printf("perspective()\n");
  470. #endif
  471.  
  472.     OneToOne[CurrentWid]=FALSE;
  473.     OrthoAligned[CurrentWid]=FALSE;
  474.     Dimensions[CurrentWid]=3;
  475.     ProjectionType[CurrentWid]=PROJ_PERSPECTIVE;
  476.  
  477.     fovy=angle*DEG/10.0;
  478.     cot=1.0/tan(fovy/2.0);
  479.  
  480. #if CLEAR_PROJECTION
  481.     memset(&Projection[CurrentWid][0][0],0,sizeof(Matrix));
  482. #endif
  483.  
  484.     Projection[CurrentWid][0][0]=FIXVALUE(cot/aspect);
  485.     Projection[CurrentWid][1][1]=FIXVALUE(cot);
  486.     Projection[CurrentWid][2][2]=FIXVALUE(     -(far+near)/(far-near));
  487.     Projection[CurrentWid][2][3]=FIXVALUE( -1.0);
  488.     Projection[CurrentWid][3][2]=FIXVALUE( -(2.0*far*near)/(far-near));
  489.  
  490. /*
  491.     printf("angle=%d fovy=%.2f cot=%.2f Proj=%.2f %.2f\n",angle,fovy,cot,
  492.                                             Projection[CurrentWid][0][0],Projection[CurrentWid][1][1]);
  493. */
  494.     }
  495.  
  496.  
  497. /******************************************************************************
  498. void    ortho(float left,float right,float bottom,float top,
  499.                                                         float near,float far)
  500.  
  501. ******************************************************************************/
  502. /*PROTOTYPE*/
  503. void ortho(float left,float right,float bottom,float top,float near,float far)
  504.     {
  505.     ortho2(left,right,bottom,top);
  506.  
  507.     Projection[CurrentWid][2][2]=FIXVALUE( -2.0/(far-near));
  508.     Projection[CurrentWid][3][2]=FIXVALUE( -(far+near)/(far-near));
  509.     }
  510.  
  511.  
  512. /******************************************************************************
  513. void    ortho2(float left,float right,float bottom,float top)
  514.  
  515. ******************************************************************************/
  516. /*PROTOTYPE*/
  517. void ortho2(float left,float right,float bottom,float top)
  518.     {
  519. #if MATRIX_DEBUG
  520.     printf("ortho2()\n");
  521. #endif
  522.  
  523. #if CLEAR_PROJECTION
  524.     memset(&Projection[CurrentWid][0][0],0,16*4);
  525. #endif
  526.  
  527.     Projection[CurrentWid][0][0]=FIXVALUE(2.0/(right-left));
  528.     Projection[CurrentWid][1][1]=FIXVALUE(2.0/(top-bottom));
  529.     Projection[CurrentWid][2][2]=FIXVALUE( -1.0);
  530.     Projection[CurrentWid][3][0]=FIXVALUE( -(right+left)/(right-left));
  531.     Projection[CurrentWid][3][1]=FIXVALUE( -(top+bottom)/(top-bottom));
  532.     Projection[CurrentWid][3][3]=FIXVALUE(1.0);
  533.  
  534.     ProjectionType[CurrentWid]=PROJ_ORTHO;
  535.  
  536.     OrthoAligned[CurrentWid]= ( left==(-0.5) && right==(CurrentWidth-0.5) &&
  537.                                                          bottom==(-0.5) && top==(CurrentHeight-0.5) );
  538.  
  539.     OneToOne[CurrentWid]=is_one_to_one(RotatePointer);
  540.     }
  541.  
  542.  
  543. /******************************************************************************
  544. void    viewport(Screencoord left,Screencoord right,
  545.                                         Screencoord bottom,Screencoord top)
  546. ******************************************************************************/
  547. /*PROTOTYPE*/
  548. void viewport(Screencoord left,Screencoord right,Screencoord bottom,Screencoord top)
  549.     {
  550.     ViewPort[CurrentWid][0]=left;
  551.     ViewPort[CurrentWid][1]=right-left+1;
  552.     ViewPort[CurrentWid][2]=bottom;
  553.     ViewPort[CurrentWid][3]=top-bottom+1;
  554.  
  555.     scrmask(left,right,bottom,top);
  556.  
  557.     OneToOne[CurrentWid]=is_one_to_one(RotatePointer);
  558.     }
  559.  
  560.  
  561. /******************************************************************************
  562. long    viewport_aligned(void)
  563.  
  564. ******************************************************************************/
  565. /*PROTOTYPE*/
  566. long viewport_aligned(void)
  567.     {
  568.     return (ViewPort[CurrentWid][0]==0 && ViewPort[CurrentWid][1]==CurrentWidth &&
  569.                                     ViewPort[CurrentWid][2]==0 && ViewPort[CurrentWid][3]==CurrentHeight );
  570.     }
  571.  
  572.  
  573. /******************************************************************************
  574. void    v2i(long lvert[2])
  575.  
  576. ******************************************************************************/
  577. /*PROTOTYPE*/
  578. void v2i(long lvert[2])
  579.     {
  580.     short svert[2];
  581.     float fvert[3];
  582.  
  583.     if(OneToOne[CurrentWid])    /* bypass transforms if no effect */
  584.         {
  585.         svert[0]=lvert[0];
  586.         svert[1]=lvert[1];
  587.         render_vertex(svert);
  588.         }
  589.     else
  590.         {
  591.         fvert[0]=lvert[0];
  592.         fvert[1]=lvert[1];
  593.         fvert[2]=0.0;
  594.  
  595.         v3f(fvert);
  596.         }
  597.     }
  598.  
  599.  
  600. /******************************************************************************
  601. void    v3i(long lvert[3])
  602.  
  603. ******************************************************************************/
  604. /*PROTOTYPE*/
  605. void v3i(long lvert[3])
  606.     {
  607.     float fvert[3];
  608.  
  609.     fvert[0]=lvert[0];
  610.     fvert[1]=lvert[1];
  611.     fvert[2]=lvert[2];
  612.  
  613.     v3f(fvert);
  614.     }
  615.  
  616.  
  617. /******************************************************************************
  618. void    v2s(short svert[2])
  619.  
  620. ******************************************************************************/
  621. /*PROTOTYPE*/
  622. void v2s(short svert[2])
  623.     {
  624.     float fvert[3];
  625.  
  626.     if(OneToOne[CurrentWid])    /* bypass transforms if no effect */
  627.         render_vertex(svert);
  628.     else
  629.         {
  630.         fvert[0]=svert[0];
  631.         fvert[1]=svert[1];
  632.         fvert[2]=0.0;
  633.  
  634.         v3f(fvert);
  635.         }
  636.     }
  637.  
  638.  
  639. /******************************************************************************
  640. void    v3s(short svert[3])
  641.  
  642. ******************************************************************************/
  643. /*PROTOTYPE*/
  644. void v3s(short svert[3])
  645.     {
  646.     float fvert[3];
  647.  
  648.     fvert[0]=svert[0];
  649.     fvert[1]=svert[1];
  650.     fvert[2]=svert[2];
  651.  
  652.     v3f(fvert);
  653.     }
  654.  
  655.  
  656. /******************************************************************************
  657. void    v2f(float fvert2[2])
  658.  
  659. ******************************************************************************/
  660. /*PROTOTYPE*/
  661. void v2f(float fvert2[2])
  662.     {
  663.     short svert[2];
  664.     float fvert[3];
  665.  
  666.     if(OneToOne[CurrentWid])    /* bypass transforms if no effect */
  667.         {
  668.         svert[0]=fvert2[0];
  669.         svert[1]=fvert2[1];
  670.         render_vertex(svert);
  671.         }
  672.     else
  673.         {
  674.         fvert[0]=fvert2[0];
  675.         fvert[1]=fvert2[1];
  676.         fvert[2]=0.0;
  677.  
  678.         v3f(fvert);
  679.         }
  680.     }
  681.  
  682.  
  683. /******************************************************************************
  684. void    v3f(float vert[3])
  685.  
  686. ******************************************************************************/
  687. /*PROTOTYPE*/
  688. void v3f(float vert[3])
  689.     {
  690.     short svert[2];
  691.     FIXTYPE fvert[3],rvert[3],pvert[3];
  692.  
  693. #if FIXED_POINT
  694.  
  695.     fvert[0]=FIXVALUE(vert[0]);
  696.     fvert[1]=FIXVALUE(vert[1]);
  697.     fvert[2]=FIXVALUE(vert[2]);
  698.     rotate_translate_position(fvert,rvert);
  699.  
  700. #else
  701.  
  702.     rotate_translate_position(vert,rvert);
  703.  
  704. #endif
  705.  
  706.     project_vertex(rvert,pvert);
  707.  
  708. /*
  709.     svert[0]=CurrentWidth  * FIXBACK(FIXDIVIDE((pvert[0]+1.0),2.0)) + 0.5;
  710.     svert[1]=CurrentHeight * FIXBACK(FIXDIVIDE((pvert[1]+1.0),2.0)) + 0.5;
  711. */
  712.  
  713.     svert[0]=ViewPort[CurrentWid][0]+ ViewPort[CurrentWid][1] * FIXBACK(FIXDIVIDE((pvert[0]+1.0),2.0));
  714.     svert[1]=ViewPort[CurrentWid][2]+ ViewPort[CurrentWid][3] * FIXBACK(FIXDIVIDE((pvert[1]+1.0),2.0));
  715.  
  716.     render_vertex(svert);
  717.  
  718. #if VERTEX_DEBUG
  719.     if(CurrentWid==1)
  720.         {
  721.         for(y=0;y<4;y++)
  722.             {
  723.             for(x=0;x<4;x++)
  724.                 printf("%5.2f ",Projection[CurrentWid][y][x]);
  725.  
  726.             printf(" ");
  727.  
  728.             for(x=0;x<4;x++)
  729.                 printf("%5.2f ",PROJECTION(y,x));
  730.  
  731.             printf(" ");
  732.  
  733.             for(x=0;x<4;x++)
  734.                 printf("%4.1f ",Transformation[CurrentWid][MatrixLevel[CurrentWid]][y][x]);
  735.  
  736.             printf(" ");
  737.  
  738.             if(y<3)
  739.                 {
  740.                 for(x=0;x<3;x++)
  741.                     printf("%4.1f ",ROTATION(y,x));
  742.  
  743.                 printf("%4.1f\n",TRANSLATION(y));
  744.                 }
  745.  
  746.             printf("\n");
  747.             }
  748.  
  749.         printf("%d %d  %d %d  %d\n",    &Projection[CurrentWid][0][0],
  750.                                     ProjectionPointer,
  751.                                     &Transformation[CurrentWid][MatrixLevel[CurrentWid]][0][0],
  752.                                     RotatePointer,
  753.                                     TranslatePointer);
  754.         printf("W%d M%d ",CurrentWid,MatrixLevel[CurrentWid]);
  755.         printf("%5.3f %5.3f %5.3f -> ",vert[0],vert[1],vert[2]);
  756.         printf("%5.3f %5.3f %5.3f -> ",rvert[0],rvert[1],rvert[2]);
  757.         printf("%5.3f %5.3f -> ",pvert[0],pvert[1]);
  758.         printf("%4d %4d\n",svert[0],svert[1]);
  759.         }
  760. #endif
  761.     }
  762.  
  763.  
  764. /******************************************************************************
  765. void    rotate_translate_position(FIXTYPE vert[3],FIXTYPE rvert[3])
  766.  
  767.     calls rotate_position()
  768.     adds Translation[]
  769. ******************************************************************************/
  770. /*NO PROTOTYPE*/
  771. void rotate_translate_position(FIXTYPE vert[3],FIXTYPE rvert[3])
  772.     {
  773. /*     short y,m; */
  774.  
  775.     rotate_position(vert,rvert);
  776.  
  777. #if FALSE
  778.     m=MatrixLevel[CurrentWid];
  779.  
  780.     /* the original (keep for reference) */
  781.     for(y=0;y<3;y++)
  782.         rvert[y]+=Translation[CurrentWid][m][y];
  783. #endif
  784.  
  785.     rvert[0]+=TRANSLATION(0);
  786.     rvert[1]+=TRANSLATION(1);
  787.     rvert[2]+=TRANSLATION(2);
  788.     }
  789.  
  790.  
  791. /******************************************************************************
  792. void    rotate_position(FIXTYPE vert[3],FIXTYPE rvert[3])
  793.  
  794.     premultiplies vector to rotational matrix transform
  795. ******************************************************************************/
  796. /*NO PROTOTYPE*/
  797. void rotate_position(FIXTYPE vert[3],FIXTYPE rvert[3])
  798.     {
  799.     short d;
  800. /*     short x,y,m; */
  801.  
  802.     d=Dimensions[CurrentWid];
  803.  
  804. #if FALSE
  805.     m=MatrixLevel[CurrentWid];
  806.  
  807.     /* the original (keep for reference) */
  808.     for(x=0;x<d;x++)
  809.         {
  810.         rvert[x]=0.0;
  811.         for(y=0;y<d;y++)
  812.             rvert[x]+=vert[y]*Rotate[CurrentWid][m][y][x];
  813.         }
  814. #endif
  815.  
  816.     /* unrolled and optimised */
  817.     if(d==3)
  818.         {
  819.         rvert[0]=    FIXMULT(vert[0],ROTATION(0,0))
  820.                 +    FIXMULT(vert[1],ROTATION(1,0))
  821.                 +    FIXMULT(vert[2],ROTATION(2,0));
  822.  
  823.         rvert[1]=    FIXMULT(vert[0],ROTATION(0,1))
  824.                 +    FIXMULT(vert[1],ROTATION(1,1))
  825.                 +    FIXMULT(vert[2],ROTATION(2,1));
  826.  
  827.         rvert[2]=    FIXMULT(vert[0],ROTATION(0,2))
  828.                 +    FIXMULT(vert[1],ROTATION(1,2))
  829.                 +    FIXMULT(vert[2],ROTATION(2,2));
  830.         }
  831.     else
  832.         {
  833.         rvert[0]=    FIXMULT(vert[0],ROTATION(0,0))
  834.                 +    FIXMULT(vert[1],ROTATION(1,0));
  835.  
  836.         rvert[1]=    FIXMULT(vert[0],ROTATION(0,1))
  837.                 +    FIXMULT(vert[1],ROTATION(1,1));
  838.  
  839.         rvert[2]=    vert[2];
  840.         }
  841.     }
  842.  
  843.  
  844. /******************************************************************************
  845. void    translate(float fx,float fy,float fz)
  846.  
  847. ******************************************************************************/
  848. /*PROTOTYPE*/
  849. void translate(float fx,float fy,float fz)
  850.     {
  851.     FIXTYPE vert[3],rvert[3];
  852. /*     short y,m; */
  853.  
  854.     OneToOne[CurrentWid]=FALSE;
  855.  
  856. #if MATRIX_DEBUG
  857.     printf("translate(%.2f %.2f %.2f)\n",fx,fy,fz);
  858. #endif
  859.  
  860.     vert[0]=FIXVALUE(fx);
  861.     vert[1]=FIXVALUE(fy);
  862.     vert[2]=FIXVALUE(fz);
  863.  
  864.     rotate_position(vert,rvert);
  865.  
  866. #if FALSE
  867.     m=MatrixLevel[CurrentWid];
  868.  
  869.     /* the original (keep for reference) */
  870.     for(y=0;y<3;y++)
  871.         Translation[CurrentWid][m][y]+=rvert[y];
  872. #endif
  873.  
  874.     /* unrolled and optimised */
  875.     TRANSLATION(0)+=rvert[0];
  876.     TRANSLATION(1)+=rvert[1];
  877.     TRANSLATION(2)+=rvert[2];
  878.     }
  879.  
  880.  
  881. /******************************************************************************
  882. void    rot(float angle,long axis)
  883.  
  884.     angle in degrees
  885.  
  886.     rotates current matrix transform about an axis
  887. ******************************************************************************/
  888. /*PROTOTYPE*/
  889. void rot(float angle,long axis)
  890.     {
  891.     short i,j;
  892.     short angle1,angle2;
  893.  
  894.     FIXTYPE b,c;
  895.     FIXTYPE sina,cosa;
  896.  
  897.     OneToOne[CurrentWid]=FALSE;
  898.  
  899. #if MATRIX_DEBUG
  900.     printf("rot(%.2f,%c)\n",angle,axis);
  901. #endif
  902.  
  903. #if SINE_TABLE
  904.  
  905.     if(angle<0.0)
  906.         {
  907.         angle1=(long)(-angle*10.0)%3600;
  908.         sina= -Sine[angle1];
  909.         }
  910.     else
  911.         {
  912.         angle1=(long)(angle*10.0)%3600;
  913.         sina=Sine[angle1];
  914.         }
  915.  
  916.     angle2=(abs((long)(angle*10.0))+900)%3600;
  917.     cosa=Sine[angle2];
  918.  
  919. #else
  920.  
  921.     angle*=DEG;
  922.  
  923.     sina=sin(angle);
  924.     cosa=cos(angle);
  925.  
  926. #endif
  927.  
  928.     switch(axis)
  929.         {
  930.         case 'x':
  931.             Dimensions[CurrentWid]=3;
  932. #if FAST_ROT
  933.             b=ROTATION(1,0);
  934.             c=ROTATION(2,0);
  935.             ROTATION(1,0)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  936.             ROTATION(2,0)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  937.  
  938.             b=ROTATION(1,1);
  939.             c=ROTATION(2,1);
  940.             ROTATION(1,1)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  941.             ROTATION(2,1)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  942.  
  943.             b=ROTATION(1,2);
  944.             c=ROTATION(2,2);
  945.             ROTATION(1,2)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  946.             ROTATION(2,2)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  947. #else
  948.             i=1;
  949.             j=2;
  950. #endif
  951.             break;
  952.  
  953.         case 'y':
  954.             Dimensions[CurrentWid]=3;
  955. #if FAST_ROT
  956.             b=ROTATION(2,0);
  957.             c=ROTATION(0,0);
  958.             ROTATION(2,0)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  959.             ROTATION(0,0)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  960.  
  961.             b=ROTATION(2,1);
  962.             c=ROTATION(0,1);
  963.             ROTATION(2,1)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  964.             ROTATION(0,1)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  965.  
  966.             b=ROTATION(2,2);
  967.             c=ROTATION(0,2);
  968.             ROTATION(2,2)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  969.             ROTATION(0,2)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  970. #else
  971.             i=2;
  972.             j=0;
  973. #endif
  974.             break;
  975.  
  976.         case 'z':
  977. #if FAST_ROT
  978.             b=ROTATION(0,0);
  979.             c=ROTATION(1,0);
  980.             ROTATION(0,0)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  981.             ROTATION(1,0)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  982.  
  983.             b=ROTATION(0,1);
  984.             c=ROTATION(1,1);
  985.             ROTATION(0,1)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  986.             ROTATION(1,1)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  987.  
  988.             b=ROTATION(0,2);
  989.             c=ROTATION(1,2);
  990.             ROTATION(0,2)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  991.             ROTATION(1,2)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  992. #else
  993.             i=0;
  994.             j=1;
  995. #endif
  996.             break;
  997.  
  998.         default:
  999.             return;
  1000.         }
  1001.  
  1002. #if FALSE
  1003.     m=MatrixLevel[CurrentWid];
  1004.  
  1005.     /* the original (keep for reference) */
  1006.     for(x=0;x<3;x++)
  1007.         {
  1008.         b=Rotate[CurrentWid][m][i][x];
  1009.         c=Rotate[CurrentWid][m][j][x];
  1010.         Rotate[CurrentWid][m][i][x]=  b*cosa+c*sina;
  1011.         Rotate[CurrentWid][m][j][x]= -b*sina+c*cosa;
  1012.         }
  1013. #endif
  1014.  
  1015. #if !FAST_ROT
  1016.  
  1017.     /* unrolled and optimised (general case) */
  1018.     b=ROTATION(i,0);
  1019.     c=ROTATION(j,0);
  1020.     ROTATION(i,0)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  1021.     ROTATION(j,0)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  1022.  
  1023.     b=ROTATION(i,1);
  1024.     c=ROTATION(j,1);
  1025.     ROTATION(i,1)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  1026.     ROTATION(j,1)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  1027.  
  1028.     b=ROTATION(i,2);
  1029.     c=ROTATION(j,2);
  1030.     ROTATION(i,2)= FIXMULT( b,cosa) + FIXMULT(c,sina);
  1031.     ROTATION(j,2)= FIXMULT(-b,sina) + FIXMULT(c,cosa);
  1032.  
  1033. #endif
  1034.     }
  1035.  
  1036.  
  1037. /******************************************************************************
  1038. void    scale(float sx,float sy,float sz)
  1039.  
  1040. ******************************************************************************/
  1041. /*PROTOTYPE*/
  1042. void scale(float sx,float sy,float sz)
  1043.     {
  1044. /*     short x,m; */
  1045.  
  1046. #if FIXED_POINT
  1047.     FIXTYPE sx2,sy2,sz2;
  1048.  
  1049.     sx2=FIXVALUE(sx);
  1050.     sy2=FIXVALUE(sy);
  1051.     sz2=FIXVALUE(sz);
  1052.  
  1053.     /* unrolled and optimised */
  1054.     ROTATION(0,0)*=sx2/FIXING_POINT;
  1055.     ROTATION(1,0)*=sy2/FIXING_POINT;
  1056.     ROTATION(2,0)*=sz2/FIXING_POINT;
  1057.  
  1058.     ROTATION(0,1)*=sx2/FIXING_POINT;
  1059.     ROTATION(1,1)*=sy2/FIXING_POINT;
  1060.     ROTATION(2,1)*=sz2/FIXING_POINT;
  1061.  
  1062.     ROTATION(0,2)*=sx2/FIXING_POINT;
  1063.     ROTATION(1,2)*=sy2/FIXING_POINT;
  1064.     ROTATION(2,2)*=sz2/FIXING_POINT;
  1065. #else
  1066.     /* unrolled and optimised */
  1067.     ROTATION(0,0)*=sx;
  1068.     ROTATION(1,0)*=sy;
  1069.     ROTATION(2,0)*=sz;
  1070.  
  1071.     ROTATION(0,1)*=sx;
  1072.     ROTATION(1,1)*=sy;
  1073.     ROTATION(2,1)*=sz;
  1074.  
  1075.     ROTATION(0,2)*=sx;
  1076.     ROTATION(1,2)*=sy;
  1077.     ROTATION(2,2)*=sz;
  1078. #endif
  1079.  
  1080.     OneToOne[CurrentWid]=FALSE;
  1081.  
  1082. #if MATRIX_DEBUG
  1083.     printf("scale(%.2f %.2f %.2f )\n",sx,sy,sz);
  1084. #endif
  1085.  
  1086. #if FALSE
  1087.     m=MatrixLevel[CurrentWid];
  1088.  
  1089.     /* the original (keep for reference) */
  1090.     for(x=0;x<3;x++)
  1091.         {
  1092.         Rotate[CurrentWid][m][0][x]*=sx;
  1093.         Rotate[CurrentWid][m][1][x]*=sy;
  1094.         Rotate[CurrentWid][m][2][x]*=sz;
  1095.         }
  1096. #endif
  1097.  
  1098.     }
  1099.